package com.and.video.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.and.video.dao.DanmuDao;
import com.and.video.domain.Danmu;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class DanmuService {

    // Redis中存储弹幕数据的键前缀（格式：dm-video-{videoId}）
    private static final String DANMU_KEY = "dm-video-";

    // 注入弹幕数据访问对象
    @Autowired
    private DanmuDao danmuDao;


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    // 同步添加弹幕到数据库
    public void addDanmu(Danmu danmu){
        danmuDao.addDanmu(danmu);
    }

    // 异步添加弹幕到数据库（使用@Async注解实现异步执行）
    @Async
    public void asyncAddDanmu(Danmu danmu){
        danmuDao.addDanmu(danmu);
    }

    /**
            * 查询弹幕数据
     * 查询策略是优先查redis中的弹幕数据，
            * 如果没有的话查询数据库，然后把查询的数据写入redis当中
     *
             * @param videoId 视频ID
     * @param startTime 开始时间（可选，用于筛选）
            * @param endTime 结束时间（可选，用于筛选）
            * @return 弹幕列表
     */
    public List<Danmu> getDanmus(Long videoId,
                                 String startTime, String endTime) throws Exception {

        // 构建Redis键
        String key = DANMU_KEY + videoId;
        // 从Redis获取弹幕数据
        String value = redisTemplate.opsForValue().get(key);
        List<Danmu> list;

        // 如果Redis中有数据
        if(!StringUtil.isNullOrEmpty(value)){
            // 将JSON字符串解析为弹幕列表
            list = JSONArray.parseArray(value, Danmu.class);

            // 如果提供了时间范围参数，进行时间筛选
            if(!StringUtil.isNullOrEmpty(startTime)
                    && !StringUtil.isNullOrEmpty(endTime)){
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                // 解析开始和结束时间
                Date startDate = sdf.parse(startTime);
                Date endDate = sdf.parse(endTime);
                List<Danmu> childList = new ArrayList<>();

                // 遍历弹幕，筛选在指定时间范围内的弹幕
                for(Danmu danmu : list){
                    Date createTime = danmu.getCreateTime();
                    if(createTime.after(startDate) && createTime.before(endDate)){
                        childList.add(danmu);
                    }
                }
                list = childList;
            }
        }else{
            // Redis中没有数据，从数据库查询
            Map<String, Object> params = new HashMap<>();
            params.put("videoId", videoId);
            params.put("startTime", startTime);
            params.put("endTime", endTime);
            list = danmuDao.getDanmus(params);

            // 将查询结果保存到Redis中，以便下次快速访问
            redisTemplate.opsForValue().set(key, JSONObject.toJSONString(list));
        }
        return list;
    }

    // 将弹幕添加到Redis缓存中
    public void addDanmusToRedis(Danmu danmu) {
        // 构建Redis键
        String key = DANMU_KEY + danmu.getVideoId();
        // 获取现有的弹幕数据
        String value = redisTemplate.opsForValue().get(key);
        List<Danmu> list = new ArrayList<>();

        // 如果Redis中已有数据，解析为列表
        if(!StringUtil.isNullOrEmpty(value)){
            list = JSONArray.parseArray(value, Danmu.class);
        }

        // 添加新弹幕到列表
        list.add(danmu);

        // 将更新后的列表保存回Redis
        redisTemplate.opsForValue().set(key, JSONObject.toJSONString(list));
    }
}